package away3d.animators.skeleton ;
/**
 * Author: David Lenaerts
 */


import flash.geom.Vector3D;



class SkeletonDirectionalNode extends SkeletonTreeNode
{
    
    
    /**
     * The weights for each joint. The total needs to equal 1.
     */ 
    public var forward          : SkeletonTreeNode ;
    public var backward         : SkeletonTreeNode ;
    public var left             : SkeletonTreeNode ;
    public var right            : SkeletonTreeNode ;
    private var _inputA         : SkeletonTreeNode ;
    private var _inputB         : SkeletonTreeNode ;
    private var _blendWeight    : Float ;
    private var _blendDirty     : Bool ;
    
    
    
    public function SkeletonDirectionalNode()
    {
        
        super();
        
    }
    
    
    override public function time( null, set_time ): Float ;
    
    
    override private function set_time( value : Float ) : Float
    {
        
        forward.time    = value ;
        backward.time   = value ;
        left.time       = value ;
        right.time      = value ;
        super.time      = value ;
        
        return value ;
        
    }
    
    
    override public function direction( null, set_direction ): Float ;
    
    
    // between 0 - 360
    override private function set_direction( value : Float ) : Float 
    {
        
        forward.direction   = value;
        backward.direction  = value;
        left.direction      = value;
        right.direction     = value;
        _blendDirty         = true;
        super.direction     = value;
        
        return value ;
        
    }
    
    
    override public function updatePose( skeleton : Skeleton )
    {
        
        if( _blendDirty ) updateBlend() ;
        _inputA.updatePose( skeleton ) ;
        _inputB.updatePose( skeleton ) ;
        
        var durA                        = _inputA.duration ;
        var endPose     : JointPose;
        var endPoses                    = skeletonPose.jointPoses ;
        var poses1                      = _inputA.skeletonPose.jointPoses ;
        var poses2                      = _inputB.skeletonPose.jointPoses ;
        var pose1       : JointPose ; 
        var pose2       : JointPose ;
        var p1          : Vector3D ;
        var p2          : Vector3D ;
        var tr          : Vector3D ;
        var numJoints                   = skeleton.numJoints ;
        
        // :s
        if( endPoses.length != numJoints ) endPoses.length = numJoints ;
        
        _duration = durA + _blendWeight*( _inputB.duration - durA ) ;
        
        for( i in 0...numJoints )
        {
            
            endPose = endPoses[ i ] ;
            //TODO: do also need to set endPoses[ i ] ;
            if( endPose == null ) endPose = new JointPose() ;
            
            pose1   = poses1[ i ] ;
            pose2   = poses2[ i ] ;
            p1      = pose1.translation ; 
            p2      = pose2.translation ;
            
            endPose.orientation.lerp( pose1.orientation, pose2.orientation, _blendWeight ) ;
            
            tr      = endPose.translation;
            tr.x    = p1.x + _blendWeight*( p2.x - p1.x ) ;
            tr.y    = p1.y + _blendWeight*( p2.y - p1.y ) ;
            tr.z    = p1.z + _blendWeight*( p2.z - p1.z ) ;
        
        }
        
    }
    
    
    private function updateBlend()
    {
        
        _blendDirty = false ;
        
        while( _direction < 0 ) _direction += 360 ;
        while (_direction >= 360) _direction -= 360 ;
        
        if( _direction < 90 )
        {
            
            _inputA         = forward ;
            _inputB         = right ;
            _blendWeight    = _direction/90 ;
            
        }
        else if( _direction < 180 )
        {
            
            _inputA         = right ;
            _inputB         = backward ;
            _blendWeight    = ( _direction - 90 )/90 ;
            
        }
        else if( _direction < 270 )
        {
            
            _inputA         = backward ;
            _inputB         = left ;
            _blendWeight    = ( _direction - 180 )/90 ;
            
        }
        else 
        {
            
            _inputA         = left;
            _inputB         = forward;
            _blendWeight    = ( _direction - 270 )/90 ;
            
        }
        
    }
    
    
    override public function updatePositionData()
    {
        
        if ( _blendDirty ) updateBlend() ;
        
        var deltA       = _inputA.rootDelta ;
        var deltB       = _inputB.rootDelta ;
        rootDelta.x     = deltA.x + _blendWeight*( deltB.x - deltA.x ) ;
        rootDelta.y     = deltA.y + _blendWeight*( deltB.y - deltA.y ) ;
        rootDelta.z     = deltA.z + _blendWeight*( deltB.z - deltA.z ) ;
        
    }
    
    
}
